from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError


class DataSource(models.Model):
    """数据源模型"""
    TYPE_CHOICES = (
        ('opcua', 'OPC UA'),
        ('mqtt', 'MQTT'),
    )

    name = models.CharField(
        max_length=100,
        verbose_name='名称',
        help_text='给数据源起一个易于识别的名称'
    )
    type = models.CharField(
        max_length=10,
        choices=TYPE_CHOICES,
        verbose_name='类型',
        help_text='选择数据源类型：OPC UA 或 MQTT'
    )
    connection_string = models.CharField(
        max_length=255,
        verbose_name='连接字符串',
        help_text='根据选择的类型输入相应格式的连接字符串'
    )
    description = models.TextField(
        blank=True,
        verbose_name='描述',
        help_text='可选：添加关于此数据源的补充说明'
    )
    created_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        verbose_name='创建者'
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='创建时间'
    )

    def clean(self):
        """验证连接字符串格式"""
        if self.type == 'opcua' and not self.connection_string.startswith('opc.tcp://'):
            raise ValidationError({
                'connection_string': 'OPC UA 连接字符串必须以 opc.tcp:// 开头'
            })
        elif self.type == 'mqtt' and not self.connection_string.startswith('mqtt://'):
            raise ValidationError({
                'connection_string': 'MQTT 连接字符串必须以 mqtt:// 开头'
            })

    class Meta:
        verbose_name = '数据源'
        verbose_name_plural = '数据源'
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.name} ({self.get_type_display()})"


class BaseSubscription(models.Model):
    """订阅基类"""
    CONDITION_CHOICES = (
        ('gt', '大于'),
        ('lt', '小于'),
        ('eq', '等于'),
        ('range', '范围'),
    )
    name = models.CharField(
        max_length=100,
        verbose_name='名称',
        help_text='给数据起一个易于识别的名称'
    )
    condition = models.CharField(
        max_length=10,
        choices=CONDITION_CHOICES,
        verbose_name='报警条件'
    )
    threshold_value = models.FloatField(
        verbose_name='阈值',
        help_text='触发报警的阈值'
    )
    threshold_max = models.FloatField(
        null=True,
        blank=True,
        verbose_name='最大阈值',
        help_text='范围条件时的最大值'
    )
    alert_message = models.TextField(
        verbose_name='报警提示信息',
        help_text='支持使用 {value} 表示当前值'
    )
    unit = models.CharField(
        max_length=20,
        blank=True,
        verbose_name='单位',
        help_text='数据的单位，如：℃、%、MPa等'
    )
    is_active = models.BooleanField(
        default=True,
        verbose_name='是否启用'
    )
    created_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        verbose_name='创建者'
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='创建时间'
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='更新时间'
    )

    class Meta:
        abstract = True


class OPCUASubscription(BaseSubscription):
    """OPC UA订阅"""
    data_source = models.ForeignKey(
        DataSource,
        on_delete=models.CASCADE,
        verbose_name='数据源'
    )

    node_id = models.CharField(
        max_length=255,
        verbose_name='节点ID',
        help_text='OPC UA节点ID，例如：ns=2;s=Channel1.Device1.Tag1'
    )

    class Meta:
        verbose_name = 'OPC UA订阅'
        verbose_name_plural = 'OPC UA订阅'
        unique_together = ['created_by', 'data_source', 'node_id']

    def __str__(self):
        return f"{self.data_source.name} - {self.node_id}"


'''
    MQTT订阅接收数据格式：
    {
        "timestamp": 1736305512825,
        "values": [
            {
                "id": "模拟器示例.函数.Random3",
                "v": 75,
                "q": true,
                "t": 1736305512731
            },
            {
                "id": "模拟器示例.函数.Sine4",
                "v": -3.13836384,
                "q": true,
                "t": 1736305512731
            },
            {
                "id": "模拟器示例.函数.Ramp1",
                "v": 3.13836384,
                "q": true,
                "t": 1736305512732
            }
        ]
    }
'''


class MQTTSubscription(models.Model):
    """MQTT订阅"""
    data_source = models.ForeignKey(
        DataSource,
        on_delete=models.CASCADE,
        verbose_name='数据源'
    )

    topic = models.CharField(
        max_length=255,
        verbose_name='MQTT主题',
        help_text='MQTT主题（Topic）'
    )
    is_active = models.BooleanField(
        default=True,
        verbose_name='是否启用'
    )
    created_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        verbose_name='创建者'
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='创建时间'
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='更新时间'
    )

    class Meta:
        verbose_name = 'MQTT订阅'
        verbose_name_plural = 'MQTT订阅'
        unique_together = ['created_by', 'data_source', 'topic']

    def __str__(self):
        return f"{self.data_source.name} - {self.topic}"


class MqttSubscriptionItem(BaseSubscription):
    """MQTT订阅项"""
    subscription = models.ForeignKey(
        MQTTSubscription,
        on_delete=models.CASCADE,
        verbose_name='MQTT订阅项'
    )

    values_id = models.CharField(
        max_length=255,
        verbose_name='数据键名',
        help_text='接收到JSON数据中的id名，如：data.temperature'
    )

    class Meta:
        verbose_name = 'MQTT订阅项'
        verbose_name_plural = 'MQTT订阅项'
        unique_together = ['created_by', 'subscription', 'values_id']

    def __str__(self):
        return f"{self.subscription.data_source.name} - {self.subscription.topic} - {self.values_id}"
